条件表达式

    我们会在后面的例子中使用下面的模型:

    1. from django.db import models
    2. class Client(models.Model):
    3. REGULAR = 'R'
    4. GOLD = 'G'
    5. PLATINUM = 'P'
    6. ACCOUNT_TYPE_CHOICES = (
    7. (REGULAR, 'Regular'),
    8. (GOLD, 'Gold'),
    9. (PLATINUM, 'Platinum'),
    10. )
    11. name = models.CharField(max_length=50)
    12. registered_on = models.DateField()
    13. account_type = models.CharField(
    14. max_length=1,
    15. choices=ACCOUNT_TYPE_CHOICES,
    16. )

    class When(condition=None, then=None, **lookups)[source]

    When()对象用于封装条件和它的结果,为了在条件表达式中使用。使用When()对象和使用filter() 方法类似。条件可以使用字段查找 或者 Q 来指定。结果通过使用then关键字来提供。

    一些例子:

    要注意这些值中的每一个都可以是表达式。

    1. >>> from django.db.models import Value
    2. >>> When(then__exact=0, then=1)
    3. >>> When(Q(then=0), then=1)

    class Case(*cases, **extra)[source]

    表达式就像是Python中的if ... elif ... else语句。每个提供的When()中的condition 按照顺序计算,直到得到一个真值。返回匹配When()对象的result表达式。

    一个简单的例子:

    Case() 接受任意数量的When()对象作为独立的参数。其它选项使用关键字参数提供。如果没有条件为TRUE,表达式会返回提供的default关键字参数。如果没有提供default参数,会使用Value(None)

    如果我们想要修改之前的查询,来获取基于Client跟着我们多长时间的折扣,我们应该这样使用查找:

    1. >>> a_month_ago = date.today() - timedelta(days=30)
    2. >>> a_year_ago = date.today() - timedelta(days=365)
    3. >>> # Get the discount for each Client based on the registration date
    4. >>> Client.objects.annotate(
    5. ... discount=Case(
    6. ... When(registered_on__lte=a_year_ago, then=Value('10%')),
    7. ... When(registered_on__lte=a_month_ago, then=Value('5%')),
    8. ... default=Value('0%'),
    9. ... output_field=CharField(),
    10. ... )
    11. ... ).values_list('name', 'discount')
    12. [('Jane Doe', '5%'), ('James Smith', '0%'), ('Jack Black', '10%')]

    高级查询

    条件表达式可以用于注解、聚合、查找和更新。它们也可以和其它表达式混合和嵌套。这可以让你构造更强大的条件查询。

    假设我们想要为客户端修改account_type来匹配它们的注册日期。我们可以使用条件表达式和update()放啊来实现:

    如果我们想要弄清楚每个account_type有多少客户端,要怎么做呢?我们可以在聚合函数中嵌套条件表达式来实现:

    1. >>> # Create some more Clients first so we can have something to count
    2. ... name='Jean Grey',
    3. ... account_type=Client.REGULAR,
    4. ... registered_on=date.today())
    5. >>> Client.objects.create(
    6. ... account_type=Client.PLATINUM,
    7. ... registered_on=date.today())
    8. >>> Client.objects.create(
    9. ... name='Jane Porter',
    10. ... account_type=Client.PLATINUM,
    11. ... registered_on=date.today())
    12. >>> # Get counts for each value of account_type
    13. >>> from django.db.models import IntegerField, Sum
    14. >>> Client.objects.aggregate(
    15. ... regular=Sum(
    16. ... Case(When(account_type=Client.REGULAR, then=1),
    17. ... output_field=IntegerField())
    18. ... ),
    19. ... gold=Sum(
    20. ... Case(When(account_type=Client.GOLD, then=1),
    21. ... output_field=IntegerField())
    22. ... ),
    23. ... platinum=Sum(
    24. ... Case(When(account_type=Client.PLATINUM, then=1),
    25. ... output_field=IntegerField())
    26. ... )
    27. ... )